/**
 * @author Huynh
 * 
 * This displays an offline game and also controls the flow of event.
 */

package controller;

import java.io.FileWriter;
import java.io.IOException;

import model.Game;

import android.app.Activity;
import android.content.Intent;
import android.fourrows.R;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.util.Pair;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class GameDisplay extends Activity implements OnClickListener {
	private Button[] column = new Button[7];
	FrameLayout boardLayout;
	private int height; // the height of the screen.
	private int width; // The width of the screen.
	private int size; // The size of a cell on the board.

	// The game.
	private Game game = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.i("onCreate", "inside gameDisplay");
		super.onCreate(savedInstanceState);

		// View the board.
		setContentView(R.layout.game);

		// bind listeners.
		column[0] = (Button) findViewById(R.id.button1);
		column[1] = (Button) findViewById(R.id.button2);
		column[2] = (Button) findViewById(R.id.button3);
		column[3] = (Button) findViewById(R.id.button4);
		column[4] = (Button) findViewById(R.id.button5);
		column[5] = (Button) findViewById(R.id.button6);
		column[6] = (Button) findViewById(R.id.button7);

		for (int i = 0; i < 7; i++) {
			column[i].setOnClickListener(this);
		}

		boardLayout = (FrameLayout) findViewById(R.id.board_frame);

		// get the screen size.
		getScreenSize();

		// Get game type. Create a new game of that type.
		Intent parent = getIntent();
		int type = parent.getIntExtra("game_type", 0);

		// get the number of move that have already made.
		int numberOfMoves = parent.getIntExtra("number_of_moves", -1);
		int gameDiary[] = null;
		if (numberOfMoves != -1) {
			// This is a loaded game
			// Read the game diary.
			gameDiary = parent.getIntArrayExtra("game_diary");
		}

		// get the game type.
		if (numberOfMoves == -1) {
			// This is a new game
			game = new Game(type);
		} else {

			// Create a game store the old game. We choose HuMAN_VS_HUMAN first,
			// so we can bring the game to where it should be.
			game = new Game(Constant.HUMAN_VS_HUMAN);

			// Display the old game.
			for (int i = 0; i < gameDiary.length; i++) {
				chooseColumn(gameDiary[i]);
			}

			// Change the type of the game! Now , start playing the intended
			// game.
			game.changeType(type);
		}

		// If the current player is a computer/or a network player, make it move
		// now.
		if (game.getInstanceType(game.getTurn()) != Constant.IS_HUMAN) {
			chooseColumn(3);
		}
	}

	private void getScreenSize() {
		// Get screen size
		Display display = getWindowManager().getDefaultDisplay();
		width = display.getWidth();
		height = display.getHeight();

		// Get the width of one cell.
		size = Math.min(width / 7, height / 6);
	}

	/**
	 * Display the result of the game
	 * 
	 * @param result
	 */
	public void viewResult(int result) {
		String s;
		if (result == 0) {
			s = "The first player win";
		} else if (result == 1) {
			s = "The second player win";
		} else {
			s = "Draw";
		}
		TextView tv = (TextView) findViewById(R.id.game_status);
		tv.setText(s);
	}

	/**
	 * Listen to user input.
	 */
	@Override
	public void onClick(View v) {
		// If this is not a human's turn, then do nothing.
		if (game.getInstanceType(game.getTurn()) == Constant.IS_COMP) {
			return;
		}

		// See which column the user choose
		for (int i = 0; i < 7; i++) {
			if (v.getId() == column[i].getId()) {
				chooseColumn(i);
				break;
			}
		}
	}

	/**
	 * Draw a marble at a certain cell.
	 * 
	 * @param i
	 *            The column to put the new marble.
	 */
	private void chooseColumn(int i) {
		// Get the cell to put a marble.
		Pair<Integer, Integer> p = game.move(i);
		if (p.first == -1) { // invalid move. Do nothing.
			return;
		}

		// draw a marble at (p.first, p.second)
		drawMarble(p.first, p.second, game.getPreviousTurn());

		// If the game is over, display the result.
		if (game.isOver()) {
			viewResult(game.getWinner());
		}
		
		/*
		//Show the next player's turn.
		Toast toast;
		if (game.getTurn() == 1) {
			toast = Toast.makeText(this, "The second player's turn", 200);
		} else {
			toast = Toast.makeText(this, "The first player's turn", 200);
		}
		toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
		toast.show();
		 */
	}

	// Draw a marble at the position (col, row)
	void drawMarble(int column, int row, int player) {
		// basic animation.
		Animation an = new TranslateAnimation(size * column, size * column, 0,
				size * row + 3);
		int duration = 50 * row;
		an.setDuration(duration);
		an.setFillAfter(true);

		// Display the move.
		ImageView iv = new ImageView(this);
		iv.setAdjustViewBounds(true);
		iv.setMaxHeight(size);
		iv.setMaxWidth(size);
		iv.setScaleType(ImageView.ScaleType.FIT_XY);

		if (player == 1) {
			iv.setImageResource(R.drawable.blue_marble);
		} else {
			iv.setImageResource(R.drawable.red_marble);
		}

		// Add the image to the view.
		LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
				LayoutParams.WRAP_CONTENT);
		boardLayout.addView(iv, params);
		iv.startAnimation(an);

		iv.postDelayed(new Runnable() {

			@Override
			public void run() {
				// If the next player is a COMP, make it move now.
				if (game.getInstanceType(game.getTurn()) == Constant.IS_COMP) {
					chooseColumn(3); // A computer player will ignore the
										// argument.
				}
			}
		}, duration * 2);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (!game.isOver()) {
				Intent saveGame = new Intent(this, QuitGame.class);
				startActivityForResult(saveGame, 1000);
				return true;
			} else {
				finish();
			}
		}
		return false;
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
		case 1000:
			switch (resultCode) {
			case 2: // Quit game.
				finish();
				break;
			case 1: // save game
				try {
					String fileName = data.getExtras().getString("fileName");
					saveFile(fileName);
				} catch (IOException e) {
					Toast.makeText(this, "Cannot write to file", 3000).show();
				}
				finish();
				break;
			case 3: // Continue, do nothing.
				break;
			default:
				break;
			}
			break;
		}
	}

	/**
	 * Save the game state to a file.
	 * 
	 * @param fileName
	 *            name of the text file that will be written.
	 * @throws IOException
	 */
	public void saveFile(String fileName) throws IOException {
		Pair<int[], Integer> p = game.getDiary();
		int[] gameDiary = p.first;
		Integer gameLength = p.second;

		FileWriter f = new FileWriter(Environment.getDataDirectory()
				+ "/data/android.fourrows/" + fileName);

		// Print the game type.
		f.write(game.getType() + "\n");

		// save number of steps.
		f.write(gameLength + "\n");
		for (int i = 0; i < gameLength; i++) {
			f.write((Integer) gameDiary[i] + "\n");
		}
		f.close();
	}// End function saveFile.
}
